﻿using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace BaseUi
{
    /// <summary>
    /// 日志类型
    /// </summary>
    public enum LogsType
    {
        /// <summary>
        /// 信息
        /// </summary>
        Info,
        /// <summary>
        /// 警告
        /// </summary>
        Warning,
        /// <summary>
        /// 错误
        /// </summary>
        Err,
        /// <summary>
        /// 数据库错误
        /// </summary>
        DbErr,
        /// <summary>
        /// 设备手动
        /// </summary>
        DeviceHand
    }

    /// <summary>
    /// 日志
    /// </summary>
    public static class Logs
    {
        static readonly Dictionary<LogsType, object> locks = new Dictionary<LogsType, object>();
        static Logs()
        {
            var fields = typeof(LogsType).GetFields(BindingFlags.Static | BindingFlags.Public) ?? new FieldInfo[] { };
            foreach (var field in fields)
            {
                locks.Add((LogsType)Enum.Parse(typeof(LogsType), field.Name), new object());
            }
        }

        const string logExtension = ".log";
        /// <summary>
        /// 写入日志失败
        /// </summary>
        public static Action<IEnumerable<string>, DateTime, LogsType, Exception> WriteErr = null;

        /// <summary>
        /// 写入日志
        /// </summary>
        /// <param name="content">内容</param>
        /// <param name="type">类型</param>
        /// <returns>是否写入成功</returns>
        public static void Write(IEnumerable<string> content, LogsType type = LogsType.Info, DateTime? dt = null)
        {
            if (content == null || !content.Any())
                return;

            dt ??= DateTime.Now;
            string hms = dt.Value.ToString("HH:mm:ss.fff");
            List<string> lines = new List<string>(content.Count());

            try
            {
                string path = Path.Combine(LocalFile.LogDir, type.ToString(), $"{(dt.Value.ToString("yyyyMMdd"))}{logExtension}");
                foreach (var item in content)
                    lines.AddRange($"[{hms}]{item}".Split(new string[] { Environment.NewLine }, StringSplitOptions.None));

                lock (locks[type])
                {
                    Directory.CreateDirectory(Path.GetDirectoryName(path));
                    File.AppendAllLines(path, lines, Encoding.UTF8);
                }
            }
            catch (Exception ex)
            {
                WriteErr?.Invoke(content, dt.Value, type, ex);
            }
        }

        /// <summary>
        /// 写入日志
        /// </summary>
        /// <param name="content">内容对象</param>
        /// <param name="type">类型</param>
        /// <returns>是否写入成功</returns>
        public static void Write(string content, LogsType type = LogsType.Info, DateTime? dt = null)
        {
            Write(new string[] { content }, type, dt);
        }

        /// <summary>
        /// 写入日志
        /// </summary>
        /// <param name="content">内容对象</param>
        /// <param name="type">类型</param>
        /// <returns>是否写入成功</returns>
        public static void Write(object content, LogsType type = LogsType.Info, DateTime? dt = null)
        {
            Write(JsonConvert.SerializeObject(content), type, dt);
        }

        /// <summary>
        /// 写入日志
        /// </summary>
        /// <param name="content">内容</param>
        /// <param name="contentTitle">内容标题</param>
        /// <param name="type">类型</param>
        /// <returns>是否写入成功</returns>
        public static void Write(object content, string contentTitle, LogsType type = LogsType.Info, DateTime? dt = null)
        {
            Write($"{contentTitle} {JsonConvert.SerializeObject(content)}", type, dt);
        }

        /// <summary>
        /// 写入日志
        /// </summary>
        /// <param name="ex">错误</param>
        /// <returns>是否写入成功</returns>
        public static void Write(Exception ex, LogsType type = LogsType.Err, DateTime? dt = null)
        {
            Write(ex.ToString(), type, dt);
        }

        /// <summary>
        /// 清除日志
        /// </summary>
        /// <param name="time">保留时间</param>
        /// <returns>清理的大小（字节）</returns>
        public static long Clear(TimeSpan time)
        {
            long size = 0;
            var rs = EnumHelps.GetEnumNames(typeof(LogsType));
            foreach (var item in rs)
            {
                try
                {
                    var path = Path.Combine(LocalFile.LogDir, item);
                    DirectoryInfo directoryInfo = new DirectoryInfo(path);
                    if (!directoryInfo.Exists)
                        continue;

                    var files = directoryInfo.GetFiles($"**{logExtension}", SearchOption.TopDirectoryOnly);
                    var fileDel = files.Where(o => o.CreationTime < (DateTime.Now - time));
                    foreach (var item2 in fileDel)
                    {
                        size += item2.Length;
                        item2.Delete();
                    }
                }
                catch (Exception)
                {

                }
            }
            return size;
        }
    }
}